//@author A0094511L
#include "gui.h"

const QString GUI::COMMAND_HELP_OVERALL = "help";
const QString GUI::COMMAND_HELP_ADD = "help add";
const QString GUI::COMMAND_HELP_DISPLAY = "help display";
const QString GUI::COMMAND_HELP_DELETE = "help delete";
const QString GUI::COMMAND_HELP_EDIT = "help edit";
const QString GUI::COMMAND_HELP_SEARCH = "help search";
const QString GUI::COMMAND_HELP_UNDO = "help undo";
const QString GUI::COMMAND_HELP_REDO =  "help redo";
const QString GUI::COMMAND_HELP_CLEAR = "help clear";
const QString GUI::COMMAND_HELP_DATE =  "help date";
const QString GUI::COMMAND_HELP_TIME = "help time";
const QString GUI::COMMAND_HELP_DONE = "help done";
const QString GUI::COMMAND_HELP_EXIT = "help exit";

const QString GUI::HELP_DISPLAY_OVERALL = "<span style=\" font-size:9pt; font-weight:bold;\">Commands:<br><br></span><span style =\" font-size: 9pt;\">add<br>display<br>"
									      "delete [line num]<br> done [line num] <br> edit<br>search<br>undo<br>redo<br>clear<br>date<br>time<br> exit <br> To find out more: type help [command]<br></span>";
const QString GUI::HELP_DISPLAY_ADD = "<span style=\" font-size:9pt; font-weight:bold;\">Supported add commands:<br><br></span><span style =\" font-size: 9pt;\">"
								      "add [name] on [date]<br />add [name] on [date] at [time]<br />add [name] on [date] [time]<br />add [name] by [date]<br />add [name] by [date] at [time]"
									  "<br />add [name] by [date] [time]<br />add [name] at [time]<br /> add [name] from [time ] to [time]<br />add [name] from [date ] to [date] <br />add [name]"
									  "on [date] from [time] to [time] <br />add [name] [relative day] at [time]<br />add [name] [relative day]<br />add [name] [relative day] from [time] to [time]<br /></span>";
const QString GUI::HELP_DISPLAY_DISPLAY = "<span style=\" font-size:9pt; font-weight:bold;\">Supported display:<br><br></span><span style =\" font-size: 9pt;\"> display: Default display <br> displayt:"
										  "Display all Tasks <br> displaye: Display all Events <br> displayw: Display all things happening this week <br> displayd [date]: Display things happening on [date]"
										  "<br> displaydb [date]: Display things to be done before [date] <br> displaydone: Display completed items <br> displayall: Display everything</span>";
const QString GUI::HELP_DISPLAY_DELETE = "<span style=\" font-size:9pt; font-weight:bold;\">Supported delete:<br><br></span><span style =\" font-size: 9pt;\"> delete [Line Number] to delete entry</span>";
const QString GUI::HELP_DISPLAY_EDIT = "<span style=\" font-size:9pt; font-weight:bold;\">Supported edit commands:<br><br></span><span style =\" font-size: 9pt;\"> edit [line num] n [name]: To Edit Name <br>"
							           "edit [line num]  st/et [time]: To edit time <br> edit [line num]  sd/ed [day]: To edit date <br></span>";
const QString GUI::HELP_DISPLAY_SEARCH = "<span style=\" font-size:9pt; font-weight:bold;\">Supported search commands:<br><br></span><span style =\" font-size: 9pt;\"> search [keyword(s)]</span>";
const QString GUI::HELP_DISPLAY_UNDO = "<span style=\" font-size:9pt; font-weight:bold;\">Undo previous change. Maximum of 10 undos.</span>";
const QString GUI::HELP_DISPLAY_REDO = "<span style=\" font-size:9pt; font-weight:bold;\">Undo previous redo. Maximum of 10 redos.</span>";
const QString GUI::HELP_DISPLAY_CLEAR = "<span style=\" font-size:9pt; font-weight:bold;\">Clear all data in the application. Undo to undo accidental clear</span>";
const QString GUI::HELP_DISPLAY_DATE = "<span style=\" font-size:9pt; font-weight:bold;\">Acceptable date formats: <br><br></span><span style =\" font-size: 9pt;\"> dd/MM/yy <br> ddMMyy <br> dd/MM <br> d/M <br>"
								       "monday \- friday (not case sensitive) <br> mon to fri (not case sentitive) <br> today/tdy <br> tmr/tomorrow/tml <br></span>";
const QString GUI::HELP_DISPLAY_TIME = "<span style=\" font-size:9pt; font-weight:bold;\">Acceptable time formats: <br><br></span><span style =\" font-size: 9pt;\"> hh:mm <br> hhmm <br> hh:mmam (not case sensitive)"
										"<br> hh:mmpm (not case sensitive) <br></span>";
const QString GUI::HELP_DONE = "<span style=\" font-size:9pt; font-weight:bold;\">Supported done:<br><br></span><span style =\" font-size: 9pt;\"> done [Line Number] to complete entry</span>";
const QString GUI::HELP_EXIT = "<span style=\" font-size:9pt; font-weight:bold;\">Command is to exit Application</span>";


const QString GUI::TEXT_PLACEHOLDER = "Enter Commands";
const QString GUI::COUNT_ZERO = "0";

const QString GUI::COLOR_WINDOWS_BACKGROUND;
	
const QString GUI::FILENAME_TICK_PIXMAP = ":/GUI/Resources/tick.png";
const QString GUI::FILENAME_CROSS_PIXMAP = ":/GUI/Resources/cross.png";	
	
const QString GUI::NAME_CALENDAR_NAV_BAR = "qt_calendar_navigationbar";
const QString GUI::CALENDAR_NAV_BAR_COLOR = "background-color: rgb(43,111,194); color: white;";

const QString GUI::SUGGESTION_DEFAULT_DISPLAY = "<html><head/><body><p><span style=\" font-weight:600; color:#2b77c2;font-size:10pt;\">add  </span><span style=\" font-weight:600; color:#f0f0f0;font-size:10pt;\">edit </span>"
												"<span style=\" font-weight:600; color:#2b77c2;font-size:10pt;\"> search  </span><span style=\" font-weight:600; color:#f0f0f0;font-size:10pt;\">undo </span>"
												"<span style=\" font-weight:600; color:#2b77c2;font-size:10pt;\"> display  </span><span style=\" font-weight:600; color:#f0f0f0;font-size:10pt;\">redo</span>"
												"<span style=\" font-weight:600; color:#2b77c2;font-size:10pt;\">  done  </span><span style=\" font-weight:600; color:#f0f0f0;font-size:10pt;\">help </span>"
												"<span style=\" font-weight:600; color:#2b77c2;font-size:10pt;\"> clear  </span><span style=\" font-weight:600; color:#f0f0f0;font-size:10pt;\">exit</span></p></body></html>";
const QString GUI::SUGGESTION_ADD = "<html><span style= \" font-weight:600; font-size:10pt; color:#2b77c2;\">add</span><span style=\" font-weight:600; color:#f0f0f0;font-size:10pt;\">[name] </span>"
								    "<span style=\" font-weight:600; color:#2b77c2;font-size:10pt\"> on/by  </span><span style=\" font-weight:600; color:#f0f0f0;font-size:10pt\">[date][time] </span></html>";
const QString GUI::SUGGESTION_DELETE = "<html><span style= \" font-weight:600; font-size:10pt;color:#2b77c2;\">delete</span><span style=\" font-weight:600; color:#f0f0f0;font-size:10pt;\"> [lineNumber] </span></html>";
const QString GUI::SUGGESTION_DISPLAY = "<html><span style= \" font-weight:600; font-size:10pt;color:#2b77c2;\">display</span></html>";
const QString GUI::SUGGESTION_CLEAR = "<html><span style= \" font-weight:600; font-size:10pt;color:#2b77c2;\">clear</span></html>";
const QString GUI::SUGGESTION_EDIT = "<html><span style= \" font-weight:600; font-size:10pt;color:#2b77c2;\">edit</span><span style=\" font-weight:600; color:#f0f0f0;font-size:10pt;\"> [line num]</span>"
									 "<span style= \" font-weight:600; color:#2b77c2;font-size:10pt;\"> n or st/et or sd/ed</span></html>";
const QString GUI::SUGGESTION_SEARCH = "<html><span style= \" font-weight:600; font-size:10pt;color:#2b77c2;\">search </span><span style=\" font-weight:600; color:#f0f0f0;font-size:10pt;\">[keyword(s)]</span></html>";
const QString GUI::SUGGESTION_UNDO = "<html><span style= \" font-weight:600; font-size:10pt;color:#2b77c2;\">undo</span></html>";
const QString GUI::SUGGESTION_REDO = "<html><span style= \" font-weight:600; font-size:10pt;color:#2b77c2;\">redo</span></html>";
const QString GUI::SUGGESTION_HELP =  "<html><span style= \" font-weight:600; font-size:10pt;color:#2b77c2;\">help </span><span style=\" font-weight:600; font-size:10pt;color:#f0f0f0;\">[command]</span></html>";
const QString GUI::SUGGESTION_EXIT = "<html><span style= \" font-weight:600; font-size:10pt;color:#2b77c2;\">exit</span></html>";

const QString GUI::SUGGESTION_CHAR_HINT_ADD = "a";
const QString GUI::SUGGESTION_CHAR_HINT_DELETE = "de";
const QString GUI::SUGGESTION_CHAR_HINT_DISPLAY = "di";
const QString GUI::SUGGESTION_CHAR_HINT_CLEAR = "c";
const QString GUI::SUGGESTION_CHAR_HINT_EDIT = "ed";
const QString GUI::SUGGESTION_CHAR_HINT_SEARCH = "s";
const QString GUI::SUGGESTION_CHAR_HINT_UNDO = "u";
const QString GUI::SUGGESTION_CHAR_HINT_REDO = "r";
const QString GUI::SUGGESTION_CHAR_HINT_HELP = "h";
const QString GUI::SUGGESTION_CHAR_HINT_EXIT = "ex";

const QString GUI::COLOR_SELECTED_BUTTON = "background-color: rgb(43,111,194);color:white;border:0px;";
const QString GUI::COLOR_DESELECTED_BUTTON = "background-color: rgb(240,240,240);border-width: 1px;border-color: rgb(240,240,240);border-style: solid;border-radius: 6;"
									         "padding: 3px;font-size: 12px;font-weight: bold;padding-left: 5px;padding-right: 5px;";

const QString GUI::ANCHOR_TODAY_HEADER = "today";
const QString GUI::ANCHOR_NEW_ITEM = "newItem";
	
const QString GUI::SYSTEM_TRAY_OPTION_SHOW = "Show";
const QString GUI::SYSTEM_TRAY_OPTION_CLOSE = "Close";

const QString GUI::FILENAME_SPLASHSCREEN = ":/GUI/Resources/trayIcon.jpg";
const QString GUI::CLOCK_DATE_FORMAT = "dddd, MMMM d";
const QString GUI::CLOCK_TIME_FORMAT = "hh:mm ap";
const QString GUI::CALENDAR_DATE_FORMAT= "dd/MM/yy";

const int GUI::BUFFER_SIZE = 256;
const char* GUI::STRING_REMINDER_NORMAL = "You have %d thing(s) today!";
const char* GUI::STRING_REMINDER_OVERDUE = "You have %d thing(s) today and %d thing(s) overdue!";
const QString GUI::SYSTEM_TRAY_MESSAGE_TITLE = "Reminders Today!";

const QString GUI::REGEX_SEARCH_KEYWORD = "search.*";

const QString GUI::MSG_VALID_HELP_ENTERED = "Help Displayed";

GUI::GUI(QWidget *parent)
	: QMainWindow(parent), _botControl(BotLogic::getInstance()){
	
	 _comp= NULL;
	
	 _shadowEffectOutputBox= NULL;
	 _shadowEffectNewLabel= NULL;
	 _shadowEffectClashLabel= NULL;
	
	 _tickLabel= NULL;
	 _crossLabel= NULL;
	 overduePix= NULL;

	 _enterAnimation= NULL;
	 _exitAnimation= NULL;

	 _stringListModel= NULL;

	 _trayIcon= NULL;

	 _timer= NULL;
	
	 _globalShortcut= NULL;
	
	 _highlighter= NULL;


	_className = QString("GUI");
	ui.setupUi(this);
	initializeGUI();
}


GUI::~GUI(){
	if(_comp != NULL){
		delete _comp;
	}
	if( _shadowEffectOutputBox!= NULL){
		delete _shadowEffectOutputBox;
	}
	if( _shadowEffectNewLabel!= NULL){
		delete _shadowEffectNewLabel;
	}
	if( _shadowEffectClashLabel!= NULL){
		delete _shadowEffectClashLabel;
	}
	if( _tickLabel!= NULL){
		delete _tickLabel;
	}
	if( _crossLabel!= NULL){
		delete _crossLabel;
	}
	if( overduePix!= NULL){
		delete overduePix;
	}
	if( _enterAnimation!= NULL){
		delete _enterAnimation;
	}
	if( _exitAnimation!= NULL){
		delete _exitAnimation;
	}
	if( _stringListModel!= NULL){
		delete _stringListModel;
	}
	if( _trayIcon!= NULL){
		delete _trayIcon;
	}
	if( _timer!= NULL){
		delete _timer;
	}
	if( _globalShortcut!= NULL){
		delete _globalShortcut;
	}
}


void GUI::initializeGUI(){

	setUpConnections();
	setUpKeyBoardShortCuts();
	createGlobalShortcut();
	setUpCompleter();

	setUpVariables();
	setUpAllImageFiles();
	setUpShadowGraphics();
	setUpAnimations();

	setUpClock();
	setCalendarStyle();
	setLabel();
	setUpCommandInput();
	setUpStatusBar();
	setUpSystemTray();
	setMiscWidgetSettings();
	setRegExp();
	initRemindersForToday();
	initDisplay();
}

void GUI::setUpConnections(){

	qxtLog->info() << _className << ": setUpConnections";
	//Connect Calendar's date double clicked(activated) and display what is happneing on that date clicked slot
	connect(ui.calendar,SIGNAL(activated(const QDate&)), this, SLOT(displayCalendarDate(const QDate&)));

	//Connect command inputs to:
	//1. Receive command upon pressing enter
	//2. Display the suggestions to user based on the first charcter typed in by user
	//3. Format Checker, changes the tick to cross and vice versa based on valid/invalid input entered by user
	//4. Connect up key pressed to scrolling of output box
	//5. Connect down key pressedn to scrolling of output box
	
	connect(ui.commandInput, SIGNAL(enterKeyPressed()), this, SLOT(receiveCommand()));
	connect(ui.commandInput, SIGNAL(textChanged()), this, SLOT(displaySuggestions()));
	connect(ui.commandInput, SIGNAL(textChanged()), this, SLOT(setCompleterWhenSearchCalled()));
	connect(ui.commandInput, SIGNAL(textChanged()), this, SLOT(validCommandInput()));
	connect(ui.commandInput, SIGNAL(upKeyPressed()), this, SLOT(scrollup()));
	connect(ui.commandInput, SIGNAL(downKeyPressed()), this, SLOT(scrolldown()));
	
	//Connect events, tasks, all today, overdue buttons on pressed to filter accordingly in GUI
	connect(ui.eventsButton, SIGNAL(pressed()), this, SLOT(filterEventsfromClick()));
	connect(ui.tasksButton, SIGNAL(pressed()), this, SLOT(filterTasksfromClick()));
	connect(ui.allButton, SIGNAL(pressed()), this, SLOT(filterAllfromClick()));
	connect(ui.todayButton, SIGNAL(pressed()), this, SLOT(filterTodayfromClick()));
	connect(ui.overDueButton, SIGNAL(pressed()), this, SLOT(filterOverduefromClick()));
}

void GUI::setUpKeyBoardShortCuts(){
	qxtLog->info() << _className << ": setUpKeyBoardShortCuts";
	new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Z), this, SLOT(undoCalled()));
	new QShortcut(QKeySequence(Qt::CTRL + Qt::Key_Y), this, SLOT(redoCalled()));
	connect(ui.commandInput, SIGNAL(undoShortcutPressed()), this, SLOT(undoFromCommandInput()));
	connect(ui.commandInput, SIGNAL(redoShortcutPressed()), this, SLOT(redoFromCommandInput()));
}


void GUI::setUpAllImageFiles(){
	qxtLog->info() << _className << ": setUpAllImageFiles";
	_tickLabel = new QPixmap(FILENAME_TICK_PIXMAP);
	_crossLabel = new QPixmap(FILENAME_CROSS_PIXMAP);
}

void GUI::setUpClock(){

	qxtLog->info() << _className << ": setUpClock";
	_timer = new QTimer (this);
	_timer ->start();
	connect(_timer, SIGNAL(timeout()), this, SLOT(showTime()));
}

void GUI::setCalendarStyle(){

	qxtLog->info() << _className << ": setCalendarStyle";
	setCalendarNavBarStyle();
	setCalendarCurrentDayStyle();
}
	
void GUI::setCalendarNavBarStyle(){

	qxtLog->info() << _className << "setCalendarNavBarStyle";
	QWidget *calendarNavBar = ui.calendar->findChild<QWidget *>(NAME_CALENDAR_NAV_BAR);
	if (calendarNavBar) {
		calendarNavBar->setStyleSheet(CALENDAR_NAV_BAR_COLOR);
	}
}

void GUI::setCalendarCurrentDayStyle(){
	//Color Today's date
	qxtLog->info() << _className << ": setCalendarCurrentDayStyle";
	QTextCharFormat currentDayHighlight;
	currentDayHighlight.setFontUnderline(true);
	currentDayHighlight.setFontWeight(QFont::Bold);
	currentDayHighlight.setForeground(QColor(62,119,196));

	QDate today = QDate::currentDate();
	ui.calendar->setDateTextFormat(today, currentDayHighlight);
}

void GUI::setLabel(){
	qxtLog->info() << _className << ": setLabel";
	CommonEnum::ReturnCount entryCount = _botControl.getCount();

	if(QString::number(entryCount.numOverdue) == COUNT_ZERO){
		ui.overDueCountLabel->hide();
	}else{
		ui.overDueCountLabel->show();
		ui.overDueCountLabel->setText(QString::number(entryCount.numOverdue));
	}
	if(QString::number(entryCount.numToday) == COUNT_ZERO){
		ui.todayCountLabel->hide();
	}else{
		ui.todayCountLabel->show();
		ui.todayCountLabel->setText(QString::number(entryCount.numToday));
	}
	if(QString::number(entryCount.numEvents+entryCount.numTasks) == COUNT_ZERO){
		ui.allCountLabel->hide();
	}else{
		ui.allCountLabel->show();
		ui.allCountLabel->setText(QString::number(entryCount.numEvents+entryCount.numTasks));
	}
	if(QString::number(entryCount.numEvents) == COUNT_ZERO){
		ui.eventsCountLabel->hide();
	}else{
		ui.eventsCountLabel->show();
		ui.eventsCountLabel->setText(QString::number(entryCount.numEvents));
	}
	if(QString::number(entryCount.numTasks) == COUNT_ZERO){
		ui.tasksCountLabel->hide();
	}else{
		ui.tasksCountLabel->show();
		ui.tasksCountLabel->setText(QString::number(entryCount.numTasks));
	}
}

void GUI::setUpVariables(){
	qxtLog->info() << _className << ": setUpVariables";
	_formatCheckerLabelWidth = ui.formatCheckerLabel->width();
	_formatCheckerLabelHeight = ui.formatCheckerLabel->height();
	_isHelpDisplayed = false;
}

void GUI::setUpSystemTray(){
	qxtLog->info() << _className << ": setUpSystemTray";
	createSystemTrayIcon();
	_trayIcon->show();
}

void GUI::setUpShadowGraphics(){
	qxtLog->info() << _className << ": setUpShadowGraphics";
	_shadowEffectOutputBox = new QGraphicsDropShadowEffect();
	_shadowEffectOutputBox->setBlurRadius(10);

	_shadowEffectNewLabel = new QGraphicsDropShadowEffect();
	_shadowEffectNewLabel->setBlurRadius(5);

	_shadowEffectClashLabel = new QGraphicsDropShadowEffect();
	_shadowEffectNewLabel->setBlurRadius(5);

	ui.textEdit->setGraphicsEffect(_shadowEffectOutputBox);
	ui.newHelp->setGraphicsEffect(_shadowEffectNewLabel);
	ui.clashHelp->setGraphicsEffect(_shadowEffectClashLabel);
}

void GUI::setUpAnimations(){
	qxtLog->info() << _className << ": setUpAnimations";
	_enterAnimation = new QPropertyAnimation(ui.HelpBox, "geometry");
	_enterAnimation->setDuration(100);
	_enterAnimation->setStartValue(QRect(-253, 30, 231, 277));
	_enterAnimation->setEndValue(QRect(24, 31, 231, 277));

	_exitAnimation = new QPropertyAnimation(ui.HelpBox, "geometry");
	_exitAnimation->setDuration(100);
	_exitAnimation->setStartValue(QRect(24, 31, 231, 277));
	_exitAnimation->setEndValue(QRect(-253, 30, 231, 277));
}

void GUI::setUpStatusBar(){

	//Set Font Color for Status Bar
	qxtLog->info() << _className << ": setUpStatusBar";
     _statusBarPalette.setColor( QPalette::WindowText, Qt::white );
     statusBar()->setPalette(_statusBarPalette);
}

void GUI::createSystemTrayIcon(){
	qxtLog->info() << _className << ": createSystemTrayIcon";
	QAction* show = new QAction(SYSTEM_TRAY_OPTION_SHOW, this);
	connect(show, SIGNAL(triggered()), this, SLOT(showNormal()));

	QAction* close = new QAction(SYSTEM_TRAY_OPTION_CLOSE, this);
	connect(close, SIGNAL(triggered()), this , SLOT(quitCmd()));

	QMenu* trayIconMenu = new QMenu(this);

	trayIconMenu->addAction(show);
	trayIconMenu->addSeparator();
	trayIconMenu->addAction(close);

	_trayIcon = new QSystemTrayIcon(this);
	_trayIcon->setContextMenu(trayIconMenu);
	_trayIcon->setIcon(QIcon(FILENAME_SPLASHSCREEN));

	connect(_trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayIconClicked(QSystemTrayIcon::ActivationReason)));

}

void GUI::createGlobalShortcut(){
	qxtLog->info() << _className << ": createGlobalShortcut";
	_globalShortcut = new QxtGlobalShortcut(this);
	connect(_globalShortcut, SIGNAL(activated()), this, SLOT(toggleVisibility()));
	_globalShortcut->setShortcut(QKeySequence(Qt::ALT + Qt::Key_Space));
}


void GUI::initRemindersForToday(){
	qxtLog->info() << _className << ": initRemindersForToday";
	CommonEnum::ReturnCount entryCount = _botControl.getCount();
	_thingsToday = entryCount.numToday;
	_thingsOverdue = entryCount.numOverdue;

	char message[BUFFER_SIZE];
	if(_thingsOverdue == 0){
	sprintf(message, STRING_REMINDER_NORMAL, _thingsToday);
	}else{
		sprintf(message,STRING_REMINDER_OVERDUE, _thingsToday, _thingsOverdue);
	}
	_trayIcon->showMessage(SYSTEM_TRAY_MESSAGE_TITLE, QString::fromLatin1(message), QSystemTrayIcon::Information);	
}
	
void GUI::resetAllButtonColors(){
	qxtLog->info() << _className << ": resetAllButtonColors";
	ui.tasksButton->setStyleSheet(COLOR_DESELECTED_BUTTON);
	ui.eventsButton->setStyleSheet(COLOR_DESELECTED_BUTTON);
	ui.allButton->setStyleSheet(COLOR_DESELECTED_BUTTON);
	ui.todayButton->setStyleSheet(COLOR_DESELECTED_BUTTON);
	ui.overDueButton->setStyleSheet(COLOR_DESELECTED_BUTTON);
}

void GUI::feedOutputToDisplay(CommonEnum::ReturnStatus output){
	qxtLog->info() << _className << ": feedOutputToDisplay";
	OutputManager converter(output.displayMsg);
	QString outputStr = converter.getFormattedString();
	if(outputStr != ""){
		ui.textEdit->setHtml(outputStr);
		ui.textEdit->scrollToAnchor(ANCHOR_NEW_ITEM);
	}
	ui.statusBar->showMessage(QString::fromStdString(output.statusMsg));
}

void GUI::updateGUIWithNewOutput(CommonEnum::ReturnStatus output){
	qxtLog->info() << _className << ": updateGUIWithNewOutput";
	feedOutputToDisplay(output);
	setLabel();
}

void GUI::initButtons(){
	qxtLog->info() << _className << ": initButtons";
	resetAllButtonColors();
	ui.allButton->setStyleSheet(COLOR_SELECTED_BUTTON );
}

void GUI::initDisplay(){
	qxtLog->info() << _className << ": initDisplay";
	CommonEnum::ReturnStatus output = _botControl.executeCommand(CommonUtils::STRING_COMMAND_DISPLAY);
	feedOutputToDisplay(output);
	initButtons();
}

void GUI::setMiscWidgetSettings(){
	qxtLog->info() << _className << ": setMiscWidgetSettings";
	ui.HelpBox->setGeometry(0,0,0,0);
	ui.formatCheckerLabel-> setPixmap(_crossLabel->scaled(_formatCheckerLabelWidth,_formatCheckerLabelHeight,Qt::KeepAspectRatio));	
	ui.textEdit->setReadOnly(true);
}

void GUI::selectButtonFromCommandInput(string userCmd){
	qxtLog->info() << _className << ": selectButtonFromCommandInput " << QString::fromStdString(userCmd);
	resetAllButtonColors();
	if(userCmd == CommonUtils::STRING_COMMAND_DISPLAY_TASK){
		ui.tasksButton->setStyleSheet(COLOR_SELECTED_BUTTON);
	} else if(userCmd == CommonUtils::STRING_COMMAND_DISPLAY_EVENT){
		ui.eventsButton->setStyleSheet(COLOR_SELECTED_BUTTON);
	} else{
		ui.allButton->setStyleSheet(COLOR_SELECTED_BUTTON);
	}
}

void GUI::setUpCommandInput(){
		//Focus added to init, changed html border
	qxtLog->info() << _className << ": setUpCommandInput";
	ui.commandInput->setFocus();
	ui.commandInput->setPlaceholderText(TEXT_PLACEHOLDER);
	_highlighter = new SyntaxHighlighter(ui.commandInput->document());
}

bool GUI::receiveandValidateHelpCommand(string userCmd){
	
	qxtLog->info() << _className << ": receiveHelpCommand" << QString::fromStdString(userCmd);
	QString helpToBeDisplayed = helpTopics(QString::fromStdString(userCmd));
	
	if((helpToBeDisplayed != "") && !_isHelpDisplayed){ //valid help command, help not displayed
		_enterAnimation->start();
		ui.HelpBox->setHtml(helpToBeDisplayed);
		_isHelpDisplayed = true;
		return true;
	}else if(helpToBeDisplayed == "" && _isHelpDisplayed){ //help displayed, invalid help command
		_exitAnimation->start();
		_isHelpDisplayed = false;
		return false;
	}else if(helpToBeDisplayed != "" && _isHelpDisplayed){ //help displayed and valid help command
		ui.HelpBox->setHtml(helpTopics(QString::fromStdString(userCmd)));
		return true;
	}else{ //help not displayed, invalid help
		//do nothing
		return false;
	}
}

void GUI::setUpCompleter(){
	qxtLog->info() << _className << ": setUpCompleter";
	_allNames = _botControl.getAllNames();
	_allNames.sort();
	_stringListModel = new QStringListModel(_allNames);
	_comp = new QCompleter(_stringListModel, this);
	_comp->setModelSorting(QCompleter::CaseSensitivelySortedModel);
}


void GUI::setRegExp(){

	qxtLog->info() << _className << ": setRegExp";

	_helpOverallFormat.setPattern(COMMAND_HELP_OVERALL);
	_helpAddFormat.setPattern(COMMAND_HELP_ADD);
	_helpDisplayFormat.setPattern(COMMAND_HELP_DISPLAY);
	_helpDeleteFormat.setPattern(COMMAND_HELP_DELETE);
	_helpEditFormat.setPattern(COMMAND_HELP_EDIT);
	_helpSearchFormat.setPattern(COMMAND_HELP_SEARCH);
	_helpUndoFormat.setPattern(COMMAND_HELP_UNDO);
	_helpRedoFormat.setPattern(COMMAND_HELP_REDO);
	_helpClearFormat.setPattern(COMMAND_HELP_CLEAR);
	_helpDateFormat.setPattern(COMMAND_HELP_DATE);
	_helpTimeFormat.setPattern(COMMAND_HELP_TIME);
	_helpDoneFormat.setPattern(COMMAND_HELP_DONE);
	_helpExitFormat.setPattern(COMMAND_HELP_EXIT);

	_helpOverallFormat.setCaseSensitivity(Qt::CaseInsensitive);
	_helpAddFormat.setCaseSensitivity(Qt::CaseInsensitive);
	_helpDisplayFormat.setCaseSensitivity(Qt::CaseInsensitive);
	_helpDeleteFormat.setCaseSensitivity(Qt::CaseInsensitive);
	_helpEditFormat.setCaseSensitivity(Qt::CaseInsensitive);
	_helpSearchFormat.setCaseSensitivity(Qt::CaseInsensitive);
	_helpUndoFormat.setCaseSensitivity(Qt::CaseInsensitive);
	_helpRedoFormat.setCaseSensitivity(Qt::CaseInsensitive);
	_helpClearFormat.setCaseSensitivity(Qt::CaseInsensitive);
	_helpDateFormat.setCaseSensitivity(Qt::CaseInsensitive);
	_helpTimeFormat.setCaseSensitivity(Qt::CaseInsensitive);
	_helpDoneFormat.setCaseSensitivity(Qt::CaseInsensitive);
	_helpExitFormat.setCaseSensitivity(Qt::CaseInsensitive);
}

QString GUI::helpTopics(QString input){
	qxtLog->info() << _className << ": helpTopics";

	if(_helpOverallFormat.exactMatch(input)){
		return HELP_DISPLAY_OVERALL;
	}else if(_helpAddFormat.exactMatch(input)){
		return HELP_DISPLAY_ADD;
	}else if(_helpDisplayFormat.exactMatch(input)){
		return HELP_DISPLAY_DISPLAY;
	}else if(_helpDeleteFormat.exactMatch(input)){
		return HELP_DISPLAY_DELETE;
	}else if(_helpEditFormat.exactMatch(input)){
		return HELP_DISPLAY_EDIT;
	}else if(_helpSearchFormat.exactMatch(input)){
		return HELP_DISPLAY_SEARCH;
	}else if(_helpUndoFormat.exactMatch(input)){
		return HELP_DISPLAY_UNDO;
	}else if(_helpRedoFormat.exactMatch(input)){
		return HELP_DISPLAY_REDO;
	}else if(_helpClearFormat.exactMatch(input)){
		return HELP_DISPLAY_CLEAR;
	}else if(_helpDateFormat.exactMatch(input)){
		return HELP_DISPLAY_DATE;
	}else if(_helpTimeFormat.exactMatch(input)){
		return HELP_DISPLAY_TIME;
	}else if(_helpDoneFormat.exactMatch(input)){
		return HELP_DONE;
	}else if(_helpExitFormat.exactMatch(input)){
		return HELP_EXIT;
	}else{
		return "";
	}
}


void GUI::receiveCommand(){
	
	qxtLog->info() << _className << "receiveCommand";
	std::string userCmd = ui.commandInput->toPlainText().toStdString();
	ui.commandInput->setText("");
	ui.suggestionsLabel->setText(SUGGESTION_DEFAULT_DISPLAY);
	selectButtonFromCommandInput(userCmd);
	if(!receiveandValidateHelpCommand(userCmd)){
		CommonEnum::ReturnStatus output = _botControl.executeCommand(userCmd);
		updateGUIWithNewOutput(output);
	}else{
		ui.statusBar->showMessage(MSG_VALID_HELP_ENTERED);
	}

	if(userCmd == CommonUtils::STRING_COMMAND_DISPLAY_TODAY)
		ui.textEdit->scrollToAnchor(ANCHOR_TODAY_HEADER);
}

void GUI::displaySuggestions(){
	QString inputStr;
	inputStr = ui.commandInput->toPlainText();
	
	if(inputStr == SUGGESTION_CHAR_HINT_ADD){
		ui.suggestionsLabel->setText(SUGGESTION_ADD);
	}
	if(inputStr == SUGGESTION_CHAR_HINT_DELETE){
		ui.suggestionsLabel->setText(SUGGESTION_DELETE);
	}
	if(inputStr == SUGGESTION_CHAR_HINT_DISPLAY){
		ui.suggestionsLabel->setText(SUGGESTION_DISPLAY);
	}
	if(inputStr == SUGGESTION_CHAR_HINT_CLEAR){
		ui.suggestionsLabel->setText(SUGGESTION_CLEAR);
	}
	if(inputStr == SUGGESTION_CHAR_HINT_EDIT){
		ui.suggestionsLabel->setText(SUGGESTION_EDIT);
	}
	if(inputStr == SUGGESTION_CHAR_HINT_SEARCH){
		ui.suggestionsLabel->setText(SUGGESTION_SEARCH);
	}
	if(inputStr == SUGGESTION_CHAR_HINT_UNDO){
		ui.suggestionsLabel->setText(SUGGESTION_UNDO);
	}
	if(inputStr == SUGGESTION_CHAR_HINT_REDO){
		ui.suggestionsLabel->setText(SUGGESTION_REDO);
	}
	if(inputStr == SUGGESTION_CHAR_HINT_HELP){
		ui.suggestionsLabel->setText(SUGGESTION_HELP);
	}
	if(inputStr == SUGGESTION_CHAR_HINT_EXIT){
		ui.suggestionsLabel->setText(SUGGESTION_EXIT);
	}
}

void GUI::validCommandInput(){	
	ui.formatCheckerLabel-> setPixmap(_crossLabel->scaled(_formatCheckerLabelWidth,_formatCheckerLabelHeight,Qt::KeepAspectRatio));
	if(_botControl.checkInputFormat(ui.commandInput->toPlainText().toStdString())){
		ui.formatCheckerLabel->setPixmap(_tickLabel->scaled(_formatCheckerLabelWidth,_formatCheckerLabelHeight,Qt::KeepAspectRatio));
	}
}


void GUI::undoCalled(){
	qxtLog->info() << _className << ": undoCalled";
	CommonEnum::ReturnStatus output = _botControl.executeCommand(CommonUtils::STRING_COMMAND_UNDO);
	updateGUIWithNewOutput(output);
}

void GUI::undoFromCommandInput(){
	qxtLog->info() << _className << ": undoFromCommandInput";
	CommonEnum::ReturnStatus output =_botControl.executeCommand(CommonUtils::STRING_COMMAND_UNDO);
	updateGUIWithNewOutput(output);
}

void GUI::redoCalled(){
	qxtLog->info() << _className << ": redoCalled";
	CommonEnum::ReturnStatus output = _botControl.executeCommand(CommonUtils::STRING_COMMAND_REDO);
	updateGUIWithNewOutput(output);
}

void GUI::redoFromCommandInput(){
	qxtLog->info() << _className << ": redoFromCommandInput";
	CommonEnum::ReturnStatus output = _botControl.executeCommand(CommonUtils::STRING_COMMAND_REDO);
	updateGUIWithNewOutput(output);
}


void GUI::displayCalendarDate(const QDate& dateClicked){
	qxtLog->info() << _className << ": displayCalendarDate";
	QString input = dateClicked.toString(CALENDAR_DATE_FORMAT);
	string inputStr = CommonUtils::STRING_COMMAND_DISPLAY_DAY + " " + input.toStdString();
	CommonEnum::ReturnStatus output = _botControl.executeCommand(inputStr);
	updateGUIWithNewOutput(output);
}

void GUI::trayIconClicked(QSystemTrayIcon::ActivationReason reason){
	qxtLog->info() << _className << ": trayIconClicked";
	if(reason == QSystemTrayIcon::Trigger){
		this->show();
	}
}

void GUI::quitCmd(){
	qxtLog->info() << _className << ": quitCmd";
	exit(0);
}

void GUI::toggleVisibility(){	
	qxtLog->info() << _className << ": toggleVisibility";
	if(this->isVisible()){		
		this->hide();
	}else{
		this->showNormal();
	}
}

void GUI::showTime(){
	QTime time = QTime::currentTime();

	QString time_text = time.toString(CLOCK_TIME_FORMAT);
	ui.DigitalTime->setText(time_text);

	QDate currentDate = QDate::currentDate();
	QString dateText = currentDate.toString(CLOCK_DATE_FORMAT);
	ui.DigitalDate->setText(dateText);

}

void GUI::filterOverduefromClick(){
	qxtLog->info() << _className << ": filterOverdueFromClicked";
	resetAllButtonColors();
	ui.overDueButton->setStyleSheet(COLOR_SELECTED_BUTTON);
	CommonEnum::ReturnStatus output = _botControl.getDefaultView();
	updateGUIWithNewOutput(output);
}

void GUI::filterTodayfromClick(){
	qxtLog->info() << _className << ": filterTodayFromClick";
	resetAllButtonColors();
	ui.todayButton->setStyleSheet(COLOR_SELECTED_BUTTON);
	CommonEnum::ReturnStatus output = _botControl.getDefaultView();
	updateGUIWithNewOutput(output);
	ui.textEdit->scrollToAnchor(ANCHOR_TODAY_HEADER);
}

void GUI::filterAllfromClick(){
	qxtLog->info() << _className << ": filterAllFromClick";
	resetAllButtonColors();
	ui.allButton->setStyleSheet(COLOR_SELECTED_BUTTON);
	CommonEnum::ReturnStatus output = _botControl.getDefaultView();
	updateGUIWithNewOutput(output);
}

void GUI::filterEventsfromClick(){
	qxtLog->info() << _className << ": filterEventsfromClick";
	resetAllButtonColors();
	ui.eventsButton->setStyleSheet(COLOR_SELECTED_BUTTON);
	_botControl.getDefaultView();
	CommonEnum::ReturnStatus output = _botControl.executeCommand(CommonUtils::STRING_COMMAND_DISPLAY_EVENT);
	updateGUIWithNewOutput(output);
}

void GUI::filterTasksfromClick(){
	qxtLog->info() << _className << ": filterTasksfromClick";
	resetAllButtonColors();
	ui.tasksButton->setStyleSheet(COLOR_SELECTED_BUTTON);
	_botControl.getDefaultView();
	CommonEnum::ReturnStatus output = _botControl.executeCommand(CommonUtils::STRING_COMMAND_DISPLAY_TASK);
	updateGUIWithNewOutput(output);
}

void GUI::scrollup(){
	qxtLog->info() << _className << ": scrollup";
	ui.textEdit->verticalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepSub);
}

void GUI::scrolldown(){
	qxtLog->info() << _className << ": scrolldown";

	ui.textEdit->verticalScrollBar()->triggerAction(QAbstractSlider::SliderSingleStepAdd);

}

void GUI::setCompleterWhenSearchCalled(){
	QString inputStr;
	inputStr = ui.commandInput->toPlainText();

	QRegExp regexForSearchCmd(REGEX_SEARCH_KEYWORD);

	if(regexForSearchCmd.exactMatch(inputStr)){
		if(ui.commandInput->completer() == NULL){
			ui.commandInput->setCompleter(_comp);
		}
		QStringList allNames = _botControl.getAllNames();
		_allNames.sort();
		_stringListModel->setStringList(allNames); 	
	}else{
		ui.commandInput->setCompleter(NULL);
	}
}